"""
本代码由[Tkinter布局助手]生成
官网:https://www.pytk.net
QQ交流群:905019785
在线反馈:https://support.qq.com/product/618914
"""
import os
import re
import time
import uuid
from datetime import datetime, timedelta
import jieba
from selenium import webdriver
from selenium.webdriver import Chrome, ActionChains, Keys
from selenium.common import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService
import requests
import tkinter as tk
import tkinter.messagebox as messagebox
from DBPool import MySQL
from douyin.comments import douyin_comments
from douyin.search import douyin_search
from lib.logger import logger

# 私信内容操作
class optionMsg(object):
    """
    私信内容操作
    """

    def __init__(self, master, mysql):
        self.msgContent = None
        self.msgType = None
        self.isEnable = None
        self.master = master
        self.mysql = mysql
        self.window = tk.Toplevel(master)
        self.window.wm_attributes('-topmost', 1)
        sw = self.window.winfo_screenwidth()
        sh = self.window.winfo_screenheight()
        ww = 375
        wh = 280
        x = (sw - ww) / 4
        y = (sh - wh) / 4
        self.window.geometry('%dx%d+%d+%d' % (ww, wh, x, y))  # 父容器大小
        self.window.title('私信')
        self.keyword = tk.StringVar()
        self.create_page()

    def create_page(self):
        logger.info("开始执行optionMsg类的create_page方法，用于创建私信配置页面")

        msg = tk.LabelFrame(self.window, text="私信配置", padx=10, pady=5)  # 水平，垂直方向上的边距均为 10
        msg.place(x=50, y=60)
        tk.Label(msg, text="私信类型:").grid(column=0, row=0, sticky='w', pady=5, padx=5)  # 添加用户账号
        tk.Label(msg, text="私信内容:").grid(column=0, row=1, sticky='w', pady=5, padx=5)  # 添加用户密码
        tk.Label(msg, text="是否启用:").grid(column=0, row=2, sticky='w', pady=5, padx=5)  # 添加用户密码

        self.msgTypeEntry = tk.Entry(msg, textvariable=self.msgType, width=23)
        self.msgTypeEntry.grid(column=1, row=0, pady=5)

        self.msgContentEntry = tk.Entry(msg, textvariable=self.msgContent, width=23)
        self.msgContentEntry.grid(column=1, row=1, pady=5)

        self.isEnableEntry = tk.Entry(msg, textvariable=self.isEnable, width=23)
        self.isEnableEntry.grid(column=1, row=2, pady=5)

        tk.Button(msg, text="确认添加", command=self.add_msg).grid(columnspan=2, row=3, pady=5, ipadx=10)

        logger.info("结束执行optionMsg类的create_page方法，私信配置页面创建完成")

    def add_msg(self):
        logger.info("开始执行optionMsg类的add_msg方法，用于添加私信信息")

        msgType = self.msgTypeEntry.get()
        msgContent = self.msgContentEntry.get()
        isEnable = self.isEnableEntry.get()
        if msgType!= '' and msgContent!= '' and isEnable!= '':
            data = {
                "私信类型": msgType,
                "私信内容": msgContent,
                "是否启用": isEnable,
                '私信ID': '',
            }
            self.master.tk_table_messageTemplateList.insert("", tk.END, values=list(data.values()))
            sql = f'INSERT INTO private_messages (type, content, isEnable) VALUES (%s,%s,%s)'
            self.mysql.insert_one(sql, (msgType, msgContent, isEnable))
            self.window.destroy()
            tk.messagebox.showinfo(title='成功', message='私信添加成功！')
        else:
            tk.messagebox.showerror('错误', '私信参数不能为空')

        logger.info("结束执行optionMsg类的add_msg方法，私信添加操作完成")


class Controller:
    # 导入UI类后，替换以下的object类型，将获得IDE属性提示功能
    ui: object

    def __init__(self):
        pass

    def init(self, ui):
        """
        得到UI实例，对组件进行初始化配置
        """
        logger.info("开始执行Controller类的init方法，用于初始化组件配置")

        self.ui = ui
        self.mysql = MySQL()
        self.initData()

        logger.info("结束执行Controller类的init方法，组件初始化配置完成")

    def print_log(self, text):
        """
        封装的接口函数，用于打印页面执行动作并更新标签文本
        :param action_text: 要打印的动作描述文本
        """
        logger.info(f"执行动作: {text}")
        self.ui.tk_label_log['text'] = '☞   ' + text + '   ☜'

    def get_mac(self):
        """ 获取服务器MAC地址 """
        mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
        return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])

    def initData(self):
        logger.info("开始执行Controller类的initData方法，用于初始化数据")

        self.print_log('初始化数据')
        self.refreshConfig()
        self.refreshMessage()
        # 获取当前日期时间
        current_datetime = datetime.now()
        # 将当前日期时间格式化为指定的字符串格式（'YYYY-MM-DD'）
        current_date = current_datetime.strftime('%Y-%m-%d')
        self.refreshVideo(current_date)

        self.refreshComment(current_date)

        self.update_follow_count(current_date)

        self.print_log('开始你的获客之旅吧，请先进行账号登录以及请求休息（菜单《关于》）获取')

        logger.info("结束执行Controller类的initData方法，数据初始化完成")

    def is_element_exist(self, element, xpath):
        try:
            element.find_element(By.XPATH, xpath)
            return True
        except NoSuchElementException:
            return False

    def refreshConfig(self):
        logger.info("开始执行Controller类的refreshConfig方法，用于刷新配置信息")

        sql_select_all = f'select * from `config` where %s limit 1'
        results = self.mysql.select_all(sql_select_all, '1=1')
        for result in results:
            self.ui.tk_input_sleepInput.config(state='normal')
            self.ui.tk_input_sleepInput.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_sleepInput.insert(0, result['collection_delay'])  # 在输入框开头插入指定的值
            self.ui.tk_input_sleepInput.config(state='readonly')

            self.ui.tk_input_keywordInput.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_keywordInput.insert(0, result['keywords'])  # 在输入框开头插入指定的值

            # 暂时将输入框状态切换为可编辑
            self.ui.tk_input_pageStart.config(state='normal')
            self.ui.tk_input_pageStart.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_pageStart.insert(0, result['video_start_page'])  # 在输入框开头插入指定的值
            self.ui.tk_input_pageStart.config(state='readonly')

            self.ui.tk_input_pageEnd.config(state='normal')
            self.ui.tk_input_pageEnd.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_pageEnd.insert(0, result['video_end_page'])  # 在输入框开头插入指定的值
            self.ui.tk_input_pageEnd.config(state='readonly')

            self.ui.tk_input_commentStart.config(state='normal')
            self.ui.tk_input_commentStart.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_commentStart.insert(0, result['comment_start_page'])  # 在输入框开头插入指定的值
            self.ui.tk_input_commentStart.config(state='readonly')

            self.ui.tk_input_commentEnd.config(state='normal')
            self.ui.tk_input_commentEnd.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_commentEnd.insert(0, result['comment_end_page'])  # 在输入框开头插入指定的值
            self.ui.tk_input_commentEnd.config(state='readonly')

            self.ui.tk_input_filterInput.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_filterInput.insert(0, result['filtering_conditions'])  # 在输入框开头插入指定的值

            self.ui.tk_text_customTextInput.delete("1.0", tk.END)  # 清空文本框
            if result['customText'] is None:
                value = ''
            else:
                value = result['customText']
            self.ui.tk_text_customTextInput.insert("1.0", value)

            self.ui.tk_label_followCount.config(text=f"已关注{result['follow_count']}个")
            self.ui.tk_label_messageCount.config(text=f"已私信{result['private_message_count']}个")

        logger.info("结束执行Controller类的refreshConfig方法，配置信息刷新完成")

    def refreshMessage(self):
        logger.info("开始执行Controller类的refreshMessage方法，用于刷新私信信息")

        sql_select_all = f'select * from `private_messages` where %s'
        results = self.mysql.select_all(sql_select_all, '1=1')
        if len(results) > 0:
            for result in results:
                data = {
                    "私信类型": result['type'],
                    "私信内容": result['content'],
                    "是否启用": result['isEnable'],
                    "私信ID": result['id']
                }
                self.ui.tk_table_messageTemplateList.insert("", tk.END, values=list(data.values()))

        logger.info("结束执行Controller类的refreshMessage方法，私信信息刷新完成")

    def refreshVideo(self, date):
        logger.info("开始执行Controller类的refreshVideo方法，用于刷新视频信息")

        try:
            for item in self.ui.tk_table_video.get_children():
                self.ui.tk_table_video.delete(item)
        except Exception as e:
            logger.error(e)
        sql_select_all = f'select * from `video_info` where %s and DATE(collection_time) = %s ORDER BY collection_time DESC, CONVERT(like_count, SIGNED) DESC'
        videoResults = self.mysql.select_all(sql_select_all, ('1=1', date))
        if len(videoResults) > 0:
            # 用于记录已经插入的行数，以便生成递增的序号
            row_count = 0
            for result in videoResults:
                data = {
                    "序号": row_count + 1,
                    "标题": result['title'],
                    "用户名": result['username'],
                    "是否采集过评论": result['is_comment'],
                    "评论数": result['comment_count'],
                    "点赞数": result['like_count'],
                    "播放数": result['play_count'],
                    "分享数": result['share_count'],
                    "收藏数": result['collect_count'],
                    "转发数": result['forward_count'],
                    "采集时间": result['collection_time'],
                    "用户id": result['user_id'],
                    "视频ID": result['video_id'],
                }
                item_id = self.ui.tk_table_video.insert("", tk.END, values=list(data.values()))
                if result['is_comment'] == '是':
                    # 设置单元格颜色为红色，这里假设要设置整个行的单元格颜色为红色
                    self.ui.tk_table_video.tag_configure('red_row', foreground='red')
                    self.ui.tk_table_video.item(item_id, tags=('red_row',))
                row_count += 1

        logger.info("结束执行Controller类的refreshVideo方法，视频信息刷新完成")

    def refreshComment(self, date):
        logger.info("开始执行Controller类的refreshComment方法，用于刷新评论信息")

        try:
            for item in self.ui.tk_table_comment.get_children():
                self.ui.tk_table_comment.delete(item)
        except Exception as e:
            logger.error(e)
        sql_select_all = f'select * from `comment_info` where %s and DATE(collection_time) = %s ORDER BY comment_time DESC, collection_time DESC'
        commentResults = self.mysql.select_all(sql_select_all, ('1=1', date))
        if len(commentResults) > 0:
            # 用于记录已经插入的行数，以便生成递增的序号
            row_count = 0
            for result in commentResults:
                data = {
                    "序号": row_count + 1,
                    "评论时间": result['comment_time'],
                    "评论内容": result['comment_content'],
                    "评论点赞": result['comment_like_count'],
                    "评论用户IP": result['comment_user_ip'],
                    "是否关注": result['is_follow'],
                    "是否私信": result['is_private_message'],
                    "评论用户": result['comment_user'],
                    "评论用户ID": result['comment_user_id'],
                    "采集时间": result['collection_time'],
                    "视频ID": result['video_id'],
                    "评论ID": result['comment_id'],
                }
                item_id = self.ui.tk_table_comment.insert("", tk.END, values=list(data.values()))
                if result['is_follow'] == '是':
                    # 设置单元格颜色为红色，这里假设要设置整个行的单元格颜色为红色
                    self.ui.tk_table_comment.tag_configure('purple_row', foreground='purple')
                    self.ui.tk_table_comment.item(item_id, tags=('purple_row',))

                if result['is_private_message'] == '是':
                    # 设置单元格颜色为红色，这里假设要设置整个行的单元格颜色为红色
                    self.ui.tk_table_comment.tag_configure('blue_row', foreground='blue')
                    self.ui.tk_table_comment.item(item_id, tags=('blue_row',))

                if result['is_follow'] == '是' and result['is_private_message'] == '是':
                    # 设置单元格颜色为红色，这里假设要设置整个行的单元格颜色为红色
                    self.ui.tk_table_comment.tag_configure('green_row', foreground='green')
                    self.ui.tk_table_comment.item(item_id, tags=('green_row',))
                row_count += 1

        logger.info("结束执行Controller类的refreshComment方法，评论信息刷新完成")

    def download_stealth_js(self, file_path,
                            url='https://raw.githubusercontent.com/requireCool/stealth.min.js/main/stealth.min.js'):
        logger.info(f"开始执行Controller类的download_stealth_js方法，用于下载stealth.js文件，文件路径：{file_path}，下载地址：{url}")

        if not os.path.exists(file_path):
            logger.info(f"{file_path} not found, downloading...")
            response = requests.get(url)
            response.raise_for_status()  # 确保请求成功
            with open(file_path, 'w') as file:
                file.write(response.text)
            logger.info(f"{file_path} downloaded.")
        else:
            logger.info(f"{file_path} already exists, no need to download.")

        logger.info(f"结束执行Controller类的download_stealth_js方法，stealth.js文件下载操作完成")

    def login(self, evt):
        logger.info("开始执行Controller类的login方法，用于登录并获取cookie信息")

        self.print_log('开始账号登录获取cookie信息')
        # TODO 组件初始化 赋值操作
        if tk.messagebox.askyesno('提示', message='开始获取抖音登陆信息，此操作需要检查浏览器相关设置并重启浏览器以确保信息获取完整准确， 是否已准备就位？'):
            options = webdriver.ChromeOptions()
            options.add_argument("headless")
            options.add_argument("--no-sandbox")
            options.add_argument("--disable-dev-shm-usage")
            options.add_argument("--disable-blink-features")
            options.add_argument("--disable-blink-features=AutomationControlled")
            options.add_argument("--disable-extensions")
            options.add_argument("--pageLoadStrategy=eager")
            options.add_argument("--disable-gpu")
            options.add_argument("--disable-software-rasterizer")
            options.add_argument("--disable-dev-shm-usage")
            options.add_argument("--ignore-certificate-errors")
            options.add_argument("--ignore-certificate-errors-spki-list")
            options.add_argument("--ignore-ssl-errors")
            options.add_experimental_option('debuggerAddress', '127.0.0.1:5003')
            service = ChromeService(executable_path=r'driver/chromedriver.exe')
            driver = Chrome(service=service, options=options)
            if tk.messagebox.askyesno('提示', message='请事先开启浏览器并确认账号已登录'):
                try:
                    url = "https://www.douyin.com/"
                    driver.get(url)
                    # self.print_log(f'你有30秒的时间扫码登录')
                    # for delaytime in range(0, 31):
                    #     self.print_log(f'已等待:{delaytime} eta:{30 - delaytime}')
                    time.sleep(5)
                    driver.refresh()
                    type = 'douyin'
                    cookies = driver.get_cookies()
                    cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies}
                    cookie = '; '.join([f"{k}={v}" for k, v in cookies_dict.items()])
                    ct = ut = int(time.time())
                    host = self.get_mac()
                    sql = f'INSERT INTO account (type, host, cookie, expired, ct, ut) VALUES (%s,%s,%s,%s,%s,%s)'
                    self.mysql.insert_one(sql, (type, host, cookie, 0, ct, ut,))
                    tk.messagebox.showinfo('成功', message='cookie保存成功')
                    self.print_log(f'cookie保存成功')
                    driver.quit()
                except Exception as e:
                    tk.messagebox.showerror('错误', message='cookie保存失败')
                    self.print_log(f'cookie保存失败')

            logger.info("结束执行Controller类的login方法，登录并获取cookie信息操作完成")

    def selectVideo(self, evt):
        logger.info("开始执行Controller类的selectVideo方法，用于选中视频")
        self.print_log(f'点击选中视频')
        selected_item = self.ui.tk_table_video.selection()
        if len(selected_item) > 1:
            tk.messagebox.showerror('错误', message='视频ID只能选择一个')
            return
        if selected_item:
            item = self.ui.tk_table_video.item(selected_item)
            values = item['values']
            video_id = self.ui.tk_input_videoIdInput.get()
            if video_id != '' and video_id != None:
                if values[-1] != int(video_id):
                    self.ui.tk_input_commentStart.config(state='normal')
                    self.ui.tk_input_commentStart.delete(0, tk.END)  # 先清空输入框内原有的内容
                    self.ui.tk_input_commentStart.insert(0, '0')  # 在输入框开头插入指定的值
                    self.ui.tk_input_commentStart.config(state='readonly')

                    self.ui.tk_input_commentEnd.config(state='normal')
                    self.ui.tk_input_commentEnd.delete(0, tk.END)  # 先清空输入框内原有的内容
                    self.ui.tk_input_commentEnd.insert(0, '0')  # 在输入框开头插入指定的值
                    self.ui.tk_input_commentEnd.config(state='readonly')
            self.ui.tk_input_videoIdInput.config(state='normal')
            self.ui.tk_input_videoIdInput.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_videoIdInput.insert(0, values[-1])  # 在输入框开头插入指定的值
            self.ui.tk_input_videoIdInput.config(state='readonly')
            logger.info(values)

        logger.info("结束执行Controller类的selectVideo方法，视频选中操作完成")

    def selectComment(self, evt):
        logger.info("开始执行Controller类的selectComment方法，用于选中评论")

        self.print_log(f'点击选中评论')
        selected_items = self.ui.tk_table_comment.selection()
        if selected_items:
            for index in reversed(selected_items):
                item = self.ui.tk_table_comment.item(index)
                values = item['values']
                logger.info(values)

        logger.info("结束执行Controller类的selectComment方法，评论选中操作完成")

    def spiderComment(self, evt):
        logger.info(f'开始执行spiderComment方法')
        self.print_log(f'开始获取评论数据')
        if tk.messagebox.askyesno('提示', message='确定开始获取评论吗'):
            try:
                self.print_log(f'加载中，请稍等')
                video_id = self.ui.tk_input_videoIdInput.get()
                if video_id == '':
                    tk.messagebox.showerror('错误', message='视频ID不能为空')
                    return
                offset = int(self.ui.tk_input_commentStart.get())
                limit = int(self.ui.tk_input_commentEnd.get())
                if offset == '' or limit == '' or limit == '0':
                    tk.messagebox.showerror('错误', message='评论页数非空')
                    return
                sql_select_all = f'select * from `request_info` where %s'
                requestResults = self.mysql.select_all(sql_select_all, '1=1')
                if not len(requestResults) > 0:
                    tk.messagebox.showerror('错误', message='请添加该环境的请求信息，F12浏览器查下/search接口的请求信息')
                    return
                if offset == 0 and limit == 0:
                    offset = 0
                    limit = 30
                else:
                    offset += 30
                    limit += 30

                # 暂时将输入框状态切换为可编辑
                self.ui.tk_input_commentStart.config(state='normal')
                self.ui.tk_input_commentStart.delete(0, tk.END)  # 先清空输入框内原有的内容
                self.ui.tk_input_commentStart.insert(0, offset)  # 在输入框开头插入指定的值
                self.ui.tk_input_commentStart.config(state='readonly')

                self.ui.tk_input_commentEnd.config(state='normal')
                self.ui.tk_input_commentEnd.delete(0, tk.END)  # 先清空输入框内原有的内容
                self.ui.tk_input_commentEnd.insert(0, limit)  # 在输入框开头插入指定的值
                self.ui.tk_input_commentEnd.config(state='readonly')
                common_params = requestResults[0]['content']
                result = douyin_comments(video_id, offset, limit, common_params)
                try:
                    if result['code'] == 0:
                        comments = result['data']['comments']
                        if len(comments) > 0:
                            commentFlag = False
                            for index, comment in enumerate(comments):
                                try:
                                    comment_content = comment['text']
                                    if self.filter_comments([comment_content])[0] is True:
                                        commentFlag = True
                                        comment_id = comment['cid']
                                        sql_select_all = f'select * from `comment_info` where comment_id=%s'
                                        commentResults = self.mysql.select_all(sql_select_all, comment_id)
                                        if len(commentResults) > 0:
                                            logger.info('评论数据已经爬取，直接跳过')
                                            continue
                                        comment_content = comment['text']
                                        comment_like_count = comment['digg_count']
                                        comment_user_id = comment['user']['uid']
                                        comment_user = comment['user']['nickname']
                                        video_id = comment['aweme_id']
                                        comment_user_ip = comment['ip_label']
                                        is_private_message = '否'
                                        is_follow = '否'
                                        comment_time = datetime.utcfromtimestamp(comment['create_time']).strftime(
                                            '%Y-%m-%d %H:%M:%S')
                                        collection_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                                        sql = f'INSERT INTO comment_info (comment_content, comment_like_count, ' \
                                              f'comment_user, comment_user_id, comment_user_ip, is_private_message, ' \
                                              f'is_follow, comment_time, collection_time, video_id, ' \
                                              f'comment_id) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
                                        self.mysql.insert_one(sql, (
                                            comment_content, comment_like_count, comment_user, comment_user_id,
                                            comment_user_ip, is_private_message, is_follow, comment_time,
                                            collection_time, video_id, comment_id))
                                except Exception as e:
                                    logger.error(e)
                                    continue
                            if commentFlag:
                                # 更新是否采集过评论信息
                                sql = (
                                    "UPDATE video_info SET is_comment=%s WHERE video_id=%s")
                                self.mysql.update_one(sql, (
                                    '是', video_id))
                                tk.messagebox.showinfo('成功', message='评论数据获取成功')
                                self.config(None, False)
                                self.print_log(f'评论数据获取成功')
                            else:
                                tk.messagebox.showerror('错误', message='暂无符合过滤条件的评论')
                        else:
                            tk.messagebox.showerror('错误', message='无评论数据')
                    elif result['code'] == 3:
                        tk.messagebox.showerror('错误', message='请先添加账号')
                        return
                except Exception as e:
                    logger.error(e)
                    tk.messagebox.showerror('错误', message='数据获取失败')
            except Exception as e:
                logger.error(e)
                tk.messagebox.showerror('错误', message='数据获取失败')
        self.refresh(None)
        logger.info(f'结束执行spiderComment方法')

    def spiderVideo(self, evt):
        logger.info(f'开始执行spiderVideo方法')
        self.print_log(f'开始获取视频数据')
        if tk.messagebox.askyesno('提示', message='确定开始获取吗'):
            try:
                self.print_log(f'加载中，请稍等')
                keyword = self.ui.tk_input_keywordInput.get()
                if keyword == '':
                    tk.messagebox.showerror('错误', message='关键词不能为空')
                    return
                sql_select_all = f'select * from `request_info` where %s'
                requestResults = self.mysql.select_all(sql_select_all, '1=1')
                if not len(requestResults) > 0:
                    tk.messagebox.showerror('错误', message='请添加该环境的请求信息，F12浏览器查下/search接口的请求信息')
                    return
                common_params = requestResults[0]['content']
                offset = int(self.ui.tk_input_pageStart.get())
                count = int(self.ui.tk_input_pageEnd.get())
                # 根据规律更新偏移量和数量
                if offset == 0 and count == 0:
                    offset = 0
                    count = 15
                else:
                    offset += count
                    count = 10
                # 暂时将输入框状态切换为可编辑
                self.ui.tk_input_pageStart.config(state='normal')
                self.ui.tk_input_pageStart.delete(0, tk.END)  # 先清空输入框内原有的内容
                self.ui.tk_input_pageStart.insert(0, offset)  # 在输入框开头插入指定的值
                self.ui.tk_input_pageStart.config(state='readonly')

                self.ui.tk_input_pageEnd.config(state='normal')
                self.ui.tk_input_pageEnd.delete(0, tk.END)  # 先清空输入框内原有的内容
                self.ui.tk_input_pageEnd.insert(0, count)  # 在输入框开头插入指定的值
                self.ui.tk_input_pageEnd.config(state='readonly')

                sql_select_all = f'select * from `video_info` where keyword=%s and search_id is not null'
                searchResults = self.mysql.select_all(sql_select_all, keyword)
                if len(searchResults) > 0:
                    search_id = searchResults[0]['search_id']
                else:
                    search_id = ''
                if offset != 0 and count != 15:
                    common_params = common_params + f"&search_id={search_id}"

                result = douyin_search(keyword, offset, count, common_params)
                try:
                    if result['code'] == 0:
                        datas = result['data']['data']
                        if len(datas) > 0:
                            for index, data in enumerate(datas):
                                try:
                                    if 'aweme_info' in data:
                                        video_id = data['aweme_info']['aweme_id']
                                        sql_select_all = f'select * from `video_info` where video_id=%s'
                                        videoResults = self.mysql.select_all(sql_select_all, video_id)
                                        if len(videoResults) > 0:
                                            logger.info('视频数据已经爬取，直接跳过')
                                            continue
                                        title = data['aweme_info']['desc']
                                        statistics = data['aweme_info']['statistics']
                                        username = data['aweme_info']['author']['nickname']
                                        user_id = data['aweme_info']['author']['uid']
                                        comment_count = statistics['comment_count']
                                        like_count = statistics['digg_count']
                                        play_count = statistics['play_count']
                                        share_count = statistics['share_count']
                                        collect_count = statistics['collect_count']
                                        forward_count = statistics['forward_count']
                                        collection_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                                        if search_id == '':
                                            search_id = result['data']['log_pb']['impr_id']
                                        sql = f'INSERT INTO video_info (video_id, search_id, keyword, title, username, user_id, ' \
                                              f'comment_count, like_count, play_count, share_count, collect_count, ' \
                                              f'forward_count, collection_time, is_comment) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, ' \
                                              f'%s, %s, %s, %s, %s);'
                                        self.mysql.insert_one(sql, (
                                            video_id, search_id, keyword, title, username, user_id, comment_count, like_count, play_count,
                                            share_count, collect_count, forward_count, collection_time, '否'))
                                except Exception as e:
                                    logger.error(e)
                                    continue
                            tk.messagebox.showinfo('成功', message='数据获取成功')
                            self.config(None, False)
                            self.print_log(f'视频数据获取成功')
                        else:
                            tk.messagebox.showerror('错误', message='无视频数据，或者接口被风控中，请一分钟后再次尝试')
                    elif result['code'] == 3:
                        tk.messagebox.showerror('错误', message='请先添加账号')
                        return
                except Exception as e:
                    logger.error(e)
                    tk.messagebox.showerror('错误', message='数据解析失败, 请检查cookie信息')
            except Exception as e:
                logger.error(e)
                tk.messagebox.showerror('错误', message='数据获取失败')
        self.refresh(None)
        logger.info(f'结束执行spiderVideo方法')

    def addMessage(self, evt):
        logger.info(f'开始执行addMessage方法')
        self.print_log(f'添加私信')
        optionMsg(self.ui, self.mysql)
        logger.info(f'结束执行addMessage方法')

    def delMessage(self, evt):
        logger.info(f'开始执行delMessage方法')
        self.print_log(f'删除私信')
        selected_items = self.ui.tk_table_messageTemplateList.selection()
        if len(selected_items) == 0:
            tk.messagebox.showerror('错误', '没有选中私信， 请至少选中一个')
        else:
            for index in reversed(selected_items):
                item = self.ui.tk_table_messageTemplateList.item(index)
                values = item['values']
                id = values[0]
                sql = f'DELETE FROM private_messages WHERE id = %s'
                self.mysql.delete_one(sql, id)
                self.ui.tk_table_messageTemplateList.delete(index)
            tk.messagebox.showinfo(title='成功', message='删除私信成功！')
        logger.info(f'结束执行delMessage方法')

    def clickVideo(self, evt):
        logger.info(f'开始执行clickVideo方法')
        self.print_log(f'点击视频列表')
        logger.info(f'结束执行clickVideo方法')

    def clickComment(self, evt):
        logger.info(f'开始执行clickComment方法')
        self.print_log(f'点击评论列表')
        logger.info(f'结束执行clickComment方法')

    def sendFollow(self, evt):
        logger.info(f'开始执行sendFollow方法')
        self.print_log(f'开始用户关注')
        try:
            # TODO 组件初始化 赋值操作
            options = webdriver.ChromeOptions()
            options.add_argument("headless")
            options.add_argument("--no-sandbox")
            options.add_argument("--disable-dev-shm-usage")
            options.add_argument("--disable-blink-features")
            options.add_argument("--disable-blink-features=AutomationControlled")
            options.add_argument("--disable-extensions")
            options.add_argument("--pageLoadStrategy=eager")
            options.add_argument("--disable-gpu")
            options.add_argument("--disable-software-rasterizer")
            options.add_argument("--disable-dev-shm-usage")
            options.add_argument("--ignore-certificate-errors")
            options.add_argument("--ignore-certificate-errors-spki-list")
            options.add_argument("--ignore-ssl-errors")
            options.add_experimental_option('debuggerAddress', '127.0.0.1:5003')
            service = ChromeService(executable_path=r'driver/chromedriver.exe')
            driver = Chrome(service=service, options=options)
            selected_items = self.ui.tk_table_comment.selection()
            if len(selected_items) == 0:
                tk.messagebox.showerror('错误', '没有选中评论， 请至少选中一个')
            else:
                for index in reversed(selected_items):
                    item = self.ui.tk_table_comment.item(index)
                    values = item['values']
                    comment_info = values[2]
                    uid = values[8]
                    comment_id = values[-1]
                    comment_user = values[7]
                    sql_select_all = f'select * from `comment_info` where comment_id=%s'
                    commentResults = self.mysql.select_all(sql_select_all, comment_id)
                    if commentResults[0]['is_follow'] == '是':
                        logger.info(f'当前用户:{comment_user}已经关注')
                        continue
                    secuid = self.getSecuidByUid(str(uid))
                    if secuid is None:
                        tk.messagebox.showerror('错误', message='获取用户secuid失败')
                        return
                    else:
                        url = f'https://www.douyin.com/user/{secuid}?from_tab_name=main'
                        driver.get(url)
                        time.sleep(5)
                        if self.is_element_exist(driver, "//span[@class='semi-button-content']"):
                            if driver.find_element(By.XPATH, "//span[@class='semi-button-content']").text == '已关注':
                                logger.info(f'当前用户:{comment_user}已经关注')
                                continue
                            else:
                                driver.find_element(By.XPATH, "//div[@class='FEvqkPxo']/Button[1]").click()
                                # 修改用户关注状态
                                sql = "UPDATE comment_info SET is_follow=%s WHERE comment_id=%s"
                                self.mysql.update_one(sql, ('是', comment_id))
                                logger.info(f'当前用户:{comment_user}关注成功')
                driver.quit()
                tk.messagebox.showinfo('成功', message='用户关注成功')
                self.refresh(None)
        except Exception as e:
            logger.error(e)
        logger.info(f'结束执行sendFollow方法')

    def sendMsg(self, evt):
        logger.info(f'开始执行sendMsg方法')
        customText = self.ui.tk_text_customTextInput.get("1.0", "end-1c")
        sql_select_all = f'select * from `private_messages` where isEnable = %s'
        result = self.mysql.select_all(sql_select_all, '是')
        if len(result) == 0 and customText == '':
            tk.messagebox.showerror('错误', message='私信模板、自定义私信均为空， 请设置')
            return

        self.print_log(f'开始用户私信')
        try:
            # TODO 组件初始化 赋值操作
            options = webdriver.ChromeOptions()
            options.add_argument("headless")
            options.add_argument("--no-sandbox")
            options.add_argument("--disable-dev-shm-usage")
            options.add_argument("--disable-blink-features")
            options.add_argument("--disable-blink-features=AutomationControlled")
            options.add_argument("--disable-extensions")
            options.add_argument("--pageLoadStrategy=eager")
            options.add_argument("--disable-gpu")
            options.add_argument("--disable-software-rasterizer")
            options.add_argument("--disable-dev-shm-usage")
            options.add_argument("--ignore-certificate-errors")
            options.add_argument("--ignore-certificate-errors-spki-list")
            options.add_argument("--ignore-ssl-errors")
            options.add_experimental_option('debuggerAddress', '127.0.0.1:5003')
            service = ChromeService(executable_path=r'driver/chromedriver.exe')
            driver = Chrome(service=service, options=options)
            selected_items = self.ui.tk_table_comment.selection()
            if len(selected_items) == 0:
                tk.messagebox.showerror('错误', '没有选中评论， 请至少选中一个')
            else:
                for index in reversed(selected_items):
                    item = self.ui.tk_table_comment.item(index)
                    values = item['values']
                    comment_info = values[2]
                    uid = values[8]
                    comment_id = values[-1]
                    comment_user = values[7]
                    sql_select_all = f'select * from `comment_info` where comment_id=%s'
                    commentResults = self.mysql.select_all(sql_select_all, comment_id)
                    if commentResults[0]['is_private_message'] == '是':
                        logger.info(f'当前用户:{comment_user}已经私信')
                        continue
                    secuid = self.getSecuidByUid(str(uid))
                    if secuid is None:
                        tk.messagebox.showerror('错误', message='获取用户secuid失败')
                        return
                    else:
                        url = f'https://www.douyin.com/user/{secuid}?from_tab_name=main'
                        driver.get(url)
                        time.sleep(10)
                        driver.find_element(By.XPATH, "//div[@class='FEvqkPxo']/Button[2]").click()
                        time.sleep(2)
                        if self.is_element_exist(driver, "//*[@data-e2e='msg-input']"):
                            self.print_log(f'私信窗口已打开')
                            customText = self.ui.tk_text_customTextInput.get("1.0", "end-1c")
                            sendMsg = '你好'
                            if customText != '':
                                sendMsg = '@' + comment_info + '。' + customText
                            else:
                                sql_select_all = f'select * from `private_messages` where isEnable = %s'
                                result = self.mysql.select_all(sql_select_all, '是')
                                if len(result) > 0:
                                    sendMsg = '@' + comment_info + '。' + result[0]['content']
                            driver.find_element(By.XPATH,
                                                "//*[@class='public-DraftStyleDefault-block public-DraftStyleDefault-ltr']").send_keys(
                                sendMsg)
                            driver.find_element(By.XPATH, "//*[contains(@class, 'e2e-send-msg-btn')]").click()
                            # 修改用户私信状态
                            sql = "UPDATE comment_info SET is_private_message=%s WHERE comment_id=%s"
                            self.mysql.update_one(sql, ('是', comment_id))
                            logger.info(f'当前用户:{comment_user}私信成功')
                driver.quit()
                tk.messagebox.showinfo('成功', message='用户私信成功')
                self.refresh(None)
        except Exception as e:
            logger.error(e)
        logger.info(f'结束执行sendMsg方法')

    def getSecuidByUid(self, id):
        logger.info(f'开始执行getSecuidByUid方法')
        # 基础URL
        base_url = 'https://www.toutiao.com/c/user/'

        # 完整的URL
        url = base_url + id + '/'
        logger.info(url)

        # 请求头
        headers = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
            "cookie": "_ac_signature=111111111111111"}

        # 发送GET请求
        response = requests.get(url, headers=headers, allow_redirects=False)

        # 检查响应状态码
        if response.status_code == 302:  # 检查是否发生重定向
            redirect_url = response.headers.get('Location')  # 获取跳转后的URL
            logger.info("跳转后的URL:", redirect_url)
            match = re.search(r'token/([^/]+)/', redirect_url)
            if match:
                token = match.group(1)
                return token  # 返回跳转后的URL
        else:
            logger.info("未发生重定向")
            return None  # 如果没有重定向，返回None
        logger.info(f'结束执行getSecuidByUid方法')

    def filter_comments(self, comments):
        logger.info(f'开始执行filter_comments方法')
        """
        过滤评论，返回一个列表，其中包含布尔值，指示每条评论是否是用户想要的。

        :param comments: 评论列表
        :return: 布尔值列表，True表示是用户想要的评论，False表示不是
        """
        keywords = self.ui.tk_input_filterInput.get().split(',')
        relevant_results = []
        for comment in comments:
            words = jieba.lcut(comment)
            relevant = any(word in keywords or word.startswith("怎么") or word.startswith("如何") for word in words)
            relevant_results.append(relevant)
        logger.info(f'结束执行filter_comments方法')
        return relevant_results

    def config(self, evt, flag=True):
        logger.info(f'开始执行config方法')
        self.print_log(f'保存配置')
        sql_select_all = f'select * from `config` where %s limit 1'
        results = self.mysql.select_all(sql_select_all, '1=1')
        sleep_input_value = self.ui.tk_input_sleepInput.get()
        keyword_input_value = self.ui.tk_input_keywordInput.get()
        if keyword_input_value != results[0]['keywords']:
            # 暂时将输入框状态切换为可编辑
            self.ui.tk_input_pageStart.config(state='normal')
            self.ui.tk_input_pageStart.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_pageStart.insert(0, '0')  # 在输入框开头插入指定的值
            self.ui.tk_input_pageStart.config(state='readonly')

            self.ui.tk_input_pageEnd.config(state='normal')
            self.ui.tk_input_pageEnd.delete(0, tk.END)  # 先清空输入框内原有的内容
            self.ui.tk_input_pageEnd.insert(0, '0')  # 在输入框开头插入指定的值
            self.ui.tk_input_pageEnd.config(state='readonly')
        page_start_value = self.ui.tk_input_pageStart.get()
        page_end_value = self.ui.tk_input_pageEnd.get()
        comment_start_value = self.ui.tk_input_commentStart.get()
        comment_end_value = self.ui.tk_input_commentEnd.get()
        filter_input_value = self.ui.tk_input_filterInput.get()
        customText = self.ui.tk_text_customTextInput.get("1.0", "end-1c")
        follow_count = 0
        private_message_count = 0
        modify_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        sql = ("UPDATE config SET collection_delay=%s,keywords=%s,video_id=%s,video_start_page=%s,video_end_page=%s,"
               "comment_start_page=%s,comment_end_page=%s,filtering_conditions=%s,browser_driver_path=%s,"
               "browser_port=%s,follow_count=%s,private_message_count=%s,customText=%s,modify_time=%s WHERE id=%s")
        self.mysql.update_one(sql, (
            sleep_input_value, keyword_input_value, None, page_start_value, page_end_value, comment_start_value,
            comment_end_value, filter_input_value, None, None
            , follow_count,
            private_message_count, customText, modify_time, results[0]['id']))
        if flag:
            tk.messagebox.showinfo('成功', message='更新成功')
        logger.info(f'结束执行config方法')

    def refresh(self, evt):
        logger.info(f'开始执行refresh方法')
        # 将字符串转换为datetime对象
        date_str = self.ui.tk_select_box_date.entry.get()
        date_obj = datetime.strptime(date_str, '%Y/%m/%d')
        # 将datetime对象再转换为指定格式的字符串
        date = date_obj.strftime('%Y-%m-%d')
        self.print_log(f'数据刷新')
        self.refreshVideo(date)
        self.refreshComment(date)
        self.refreshConfig()
        self.update_follow_count(date)
        self.expire_cookie(date)
        logger.info(f'结束执行refresh方法')

    def update_follow_count(self, date):
        logger.info(f'开始执行update_follow_count方法')
        sql_select_all = f'SELECT COUNT(*) as num FROM `comment_info` WHERE `is_follow` = %s and DATE(collection_time) = %s'
        res1 = self.mysql.select_all(sql_select_all, ('是', date))
        sql_select_all = f'SELECT COUNT(*) as num FROM `comment_info` WHERE `is_private_message` = %s and DATE(collection_time) = %s'
        res2 = self.mysql.select_all(sql_select_all, ('是', date))
        follow_count = res1[0]['num']
        private_message_count = res2[0]['num']
        self.ui.tk_label_followCount.config(text=f"已关注{follow_count}个")
        self.ui.tk_label_messageCount.config(text=f"已私信{private_message_count}个")
        logger.info(f'结束执行update_follow_count方法')

    def expire_cookie(self, date):
        logger.info(f'开始执行expire_cookie方法')
        # 获取当前时间
        current_time = datetime.now()
        # 计算两天前的时间
        two_days_ago = current_time - timedelta(days=2)
        # 将时间戳转换为日期时间格式进行比较，这里假设ct字段在名为your_table的表中
        sql = "UPDATE account SET expired=1 WHERE FROM_UNIXTIME(ct) <= %s"
        self.mysql.update_one(sql, two_days_ago)
        logger.info(f'结束执行expire_cookie方法')